import axios from "axios";
import type {
  AxiosInstance,
  AxiosResponse,
  InternalAxiosRequestConfig,
} from "axios";
import { isFunction } from "@/utils";
import { RequestEnum } from "@/config";
import { getAppEnvConfig } from "@/utils/helper/env";

//请求class
export class HttpAxios {
  //请求class实例
  private static HTTP_INSTANCE: Nullable<HttpAxios>;

  //工厂函数
  static factory(option: AxionsOptions) {
    if (!this.HTTP_INSTANCE) {
      this.HTTP_INSTANCE = new this(option);
    }
    return this.HTTP_INSTANCE;
  }

  constructor(options: AxionsOptions) {
    try {
      const {  baseUrl, mockUrl } = getAppEnvConfig();

      //存入拦截器对象 axios实例 传入的默认请求config等等
      let { interceptors } = options;
      this.INTERCEPTOR = interceptors;
      this.AXIOS_INSTANCE = axios.create({
        baseURL: import.meta.env.VITE_USE_MOCK === 'true' ? mockUrl : baseUrl,
      });
    } catch (err: any) {
      throw new Error("初始化axios失败：" + err.message ?? err);
    }

    this.useInterceptor();
  }

  private AXIOS_INSTANCE: AxiosInstance;

  //拦截器对象
  private INTERCEPTOR: AxionsOptions.AxiosInterceptors;

  //挂载拦截器
  useInterceptor() {
    try {
      let {
        requestInterceptor,
        responseInterceptor,
        responseErrorInterceptor,
      } = this.INTERCEPTOR;

      this.AXIOS_INSTANCE.interceptors.request.use(
        (config: InternalAxiosRequestConfig) => {
          if (isFunction(requestInterceptor)) {
            config = requestInterceptor(config);
          }
          return config;
        },
        undefined
      );

      this.AXIOS_INSTANCE.interceptors.response.use(
        (res: AxiosResponse<Result>) => {
          if (isFunction(responseInterceptor)) {
            // @ts-ignore
            res = responseInterceptor(res);
          }
          return res;
        },
        (error) => {
          if (isFunction(responseErrorInterceptor)) {
            error = responseErrorInterceptor(this.AXIOS_INSTANCE, error);
          }
          return error;
        }
      );
    } catch (err: any) {
      throw new Error("挂载axios拦截器出错：" + err.message ?? err);
    }
  }

  //get
  get<T, V = any>(
    params: T,
    config: AxionsOptions.RequestConfig
  ): Promise<Result<V>> {
    return this.requestHandle<V>({
      ...config,
      method: RequestEnum.GET,
      params,
    });
  }

  //post
  post<T, V = any>(
    params: T,
    config: AxionsOptions.RequestConfig
  ): Promise<Result<V>> {
    return this.requestHandle<V>({
      ...config,
      method: RequestEnum.POST,
      data: params,
    });
  }

  //put
  put<T, V = any>(
    params: T,
    config: AxionsOptions.RequestConfig
  ): Promise<Result<V>> {
    return this.requestHandle<V>({
      ...config,
      method: RequestEnum.PUT,
      data: params,
    });
  }

  //delete
  delete<T, V = any>(
    params: T,
    config: AxionsOptions.RequestConfig
  ): Promise<Result<V>> {
    return this.requestHandle<V>({
      ...config,
      method: RequestEnum.DELETE,
      data: params,
    });
  }

  //请求
  requestHandle<T = any>(cfg: AxionsOptions.RequestConfig) {
    return new Promise<Result<T>>((resolve, reject) => {
      this.AXIOS_INSTANCE.request(cfg)
        .then((res) => {
          resolve(res as unknown as Result<T>);
        })
        .catch((rej) => {
          reject(rej);
        });
    });
  }
}
